/**
 * 
 */
package com.jolestar.yayaweibotong;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.jolestar.yayaweibotong.controller.AccountAction;
import com.jolestar.yayaweibotong.controller.BindAction;
import com.jolestar.yayaweibotong.controller.CallbackAction;
import com.jolestar.yayaweibotong.controller.ForwordViewAction;
import com.jolestar.yayaweibotong.controller.DashboardAction;
import com.jolestar.yayaweibotong.controller.IndexAction;
import com.jolestar.yayaweibotong.controller.InviteTokenAction;
import com.jolestar.yayaweibotong.controller.LoginAction;
import com.jolestar.yayaweibotong.controller.LogoutAction;
import com.jolestar.yayaweibotong.controller.RedirectAction;
import com.jolestar.yayaweibotong.controller.RegisterAction;
import com.jolestar.yayaweibotong.controller.RegisterByGoogleAction;
import com.jolestar.yayaweibotong.controller.UpdateCfgAction;
import com.jolestar.yayaweibotong.controller.WebAction;
import com.jolestar.yayaweibotong.dao.UserDomain;
import com.jolestar.yayaweibotong.service.UserService;
import com.jolestar.yayaweibotong.task.CronJobAction;
import com.jolestar.yayaweibotong.task.GetStatusQueueCronJob;
import com.jolestar.yayaweibotong.task.GetStatusTask;
import com.jolestar.yayaweibotong.task.TaskAction;
import com.jolestar.yayaweibotong.task.UpdateStatusTask;
import com.jolestar.yayaweibotong.task.UpdateUserTask;
import com.jolestar.yayaweibotong.task.UserQueueCronJob;

/**
 * @author jolestar@gmail.com
 * 
 */
public class DispatchController implements Filter {

	/**
	 * 
	 */
	private static final long serialVersionUID = -766864431474647227L;

	private static final Logger log = Logger.getLogger(DispatchController.class
			.getName());

	public static final Map<String, ActionDefine> dispatchMap = new HashMap<String, ActionDefine>();
	static {
		ActionDefine define = new ActionDefine(new IndexAction(), false);
		putActionDefine(define);
		define = new ActionDefine(new RedirectAction("index.do", "/index"),
				false);
		putActionDefine(define);
		define = new ActionDefine(new ForwordViewAction("about"), false);
		putActionDefine(define);
		define = new ActionDefine(new ForwordViewAction("help"), false);
		putActionDefine(define);
		define = new ActionDefine(new LoginAction(), false);
		putActionDefine(define);
		define = new ActionDefine(new RedirectAction("login.do", "/login"),
				false);
		putActionDefine(define);
		define = new ActionDefine(new RegisterAction(), false);
		putActionDefine(define);
		define = new ActionDefine(new RegisterByGoogleAction(), false);
		putActionDefine(define);
		define = new ActionDefine(new DashboardAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new RedirectAction("home.do", "/dashboard"),
				false);
		putActionDefine(define);
		define = new ActionDefine(new RedirectAction("home", "/dashboard"),
				false);
		putActionDefine(define);
		define = new ActionDefine(new AccountAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new BindAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new CallbackAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new UpdateCfgAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new LogoutAction(), true);
		putActionDefine(define);
		define = new ActionDefine(new InviteTokenAction(), false);
		putActionDefine(define);
		define = new ActionDefine(
				new CronJobAction(new GetStatusQueueCronJob()), false);
		putActionDefine(define);
		define = new ActionDefine(new CronJobAction(new UserQueueCronJob()),
				false);
		putActionDefine(define);
		define = new ActionDefine(new TaskAction(new GetStatusTask()), false);
		putActionDefine(define);
		define = new ActionDefine(new TaskAction(new UpdateStatusTask()), false);
		putActionDefine(define);
		define = new ActionDefine(new TaskAction(new UpdateUserTask()), false);
		putActionDefine(define);
	}

	private static void putActionDefine(ActionDefine define) {
		log.info("map path:" + define.path + " to action:"
				+ define.action.getName());
		dispatchMap.put(define.path, define);
	}

	/**
	 * 
	 */
	public DispatchController() {
	}

	@Override
	public void init(FilterConfig filterconfig) throws ServletException {
		UserDomain user = UserService.ServiceHolder.getInstance()
				.getDefaultUser();
		log.info("default-user:" + user.getEmail());
	}

	@Override
	public void doFilter(ServletRequest servletrequest,
			ServletResponse servletresponse, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletrequest;
		HttpServletResponse response = (HttpServletResponse) servletresponse;
		String uri = request.getRequestURI();
		ActionDefine define = dispatchMap.get(uri);
		if (define == null) {
			chain.doFilter(servletrequest, servletresponse);
			return;
		}
		HttpSession session = request.getSession();
		UserDomain user = (session == null ? null : (UserDomain) session
				.getAttribute("user"));
		if (user != null) {
			request.setAttribute("isLogin", true);
			request.setAttribute("user", user);
		} else {
			request.setAttribute("isLogin", false);
		}
		if (define.needAuth) {
			if (user == null) {
				response.sendRedirect("/login");
				return;
			}
		}
		define.action.action(request, response);
	}

	@Override
	public void destroy() {

	}

	private static class ActionDefine {
		public WebAction action;
		public String path;
		public boolean needAuth;

		public ActionDefine(WebAction action, boolean needAuth) {
			this.action = action;
			this.path = action.getPath();
			this.needAuth = needAuth;
		}
	}

}
